package com.tms.security.config;

import com.tms.security.AuthTokenFilter;
import com.tms.security.CustomAccessDecisionManager;
import com.tms.security.CustomFilterInvocationSecurityMetadataSource;
import com.tms.security.service.UserDetailServiceImpl;
import com.tms.utils.token.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * security配置类
 *
 * @author ozj
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * security调用查找用户信息
     */
    @Autowired
    UserDetailServiceImpl userService;

    @Autowired
    TokenService tokenService;


    /**
     * 密码编码类
     *
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 在这里调用userService查找用户信息
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        //这里把两个实例设置进去
                        object.setSecurityMetadataSource(cfisms());
                        object.setAccessDecisionManager(cadm());
                        return object;
                    }
                }).and()
                .addFilter(new AuthTokenFilter(authenticationManager(), tokenService))
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling()
                //没有权限，返回json
                .accessDeniedHandler(shc().accessDeniedHandler())
                .and()
                //处理注销
                .logout()
                //路径
                .logoutUrl("/api/users/logout")
                //清除身份认证信息
                .clearAuthentication(true)
                //使session失效
                .invalidateHttpSession(true)
                .logoutSuccessHandler(shc().logoutSussHandler())
                .permitAll();
        //开启跨域访问
        http.cors().disable();
        http.csrf().disable().exceptionHandling()
                .authenticationEntryPoint(shc().getAauthenticationEntryPoint());
        //开启模拟请求，比如API POST测试工具的测试，不开启时，API POST为报403错误
    }

    @Bean
    SecurityHandlerConfig shc() {
        return new SecurityHandlerConfig();
    }

    @Bean
    CustomFilterInvocationSecurityMetadataSource cfisms() {
        return new CustomFilterInvocationSecurityMetadataSource();
    }

    @Bean
    CustomAccessDecisionManager cadm() {
        return new CustomAccessDecisionManager();
    }
}
